﻿using System.Reflection;
using Castle.DynamicProxy;
using Infrastructure.UnitWork;
using TestDDD.CustomAttribute;

namespace TestDDD.Interceptors
{
    public class TransactionInterceptor(IUnitOfWork unitOfWork) : AsyncInterceptorBase
    {
        override protected void BeforeProceed(IInvocation invocation)
        {
            MethodInfo methodInfo = invocation.MethodInvocationTarget;
            if (methodInfo.IsDefined(typeof(UseTransactionAttribute), true))
            {
                try
                {
                    UseTransactionAttribute? useTransactionAttribute = methodInfo.GetCustomAttribute<UseTransactionAttribute>();
                    if (useTransactionAttribute.TransactionType == TransactionType.DbTransaction)
                    {
                        unitOfWork.BeginTran();
                    }
                    else
                    {
                        unitOfWork.BeginUnitOfWork();
                    }
                }
                catch
                {
                    unitOfWork.RollbackTran();
                    throw;
                }
            }
        }

        override protected Task AfterProceedAsync(IInvocation invocation, bool hasAsynResult)
        {
            Proceed(invocation, IsException);
            return Task.CompletedTask;
        }

        override protected void AfterProceedSync(IInvocation invocation)
        {
            Proceed(invocation, IsException);
        }
        private void Proceed(IInvocation invocation, bool isException)
        {
            MethodInfo methodInfo = invocation.MethodInvocationTarget;
            if (methodInfo.IsDefined(typeof(UseTransactionAttribute), true))
            {
                UseTransactionAttribute? useTransactionAttribute = methodInfo.GetCustomAttribute<UseTransactionAttribute>();
                if (useTransactionAttribute?.TransactionType == TransactionType.DbTransaction)
                {
                    if (isException)
                    {
                        unitOfWork.RollbackTran();
                    }
                    else
                    {
                        unitOfWork.CommitTran();
                    }
                }
                else
                {
                    if (isException)
                    {
                        unitOfWork.DisposeUnitOfWork();
                    }
                    else
                    {
                        unitOfWork.CommitUnitOfWork();
                    }
                }
            }
        }


        //public void Intercept(IInvocation invocation)
        //{
        //    MethodInfo methodInfo = invocation.MethodInvocationTarget;
        //    if (methodInfo.IsDefined(typeof(UseTransactionAttribute), true))
        //    {
        //        try
        //        {
        //            UseTransactionAttribute? useTransactionAttribute = methodInfo.GetCustomAttribute<UseTransactionAttribute>();
        //            if (useTransactionAttribute.TransactionType == TransactionType.DbTransaction)
        //            {
        //                unitOfWork.BeginTran();
        //                invocation.Proceed();
        //                unitOfWork.CommitTran();
        //            }
        //            else
        //            {
        //                unitOfWork.BeginUnitOfWork();
        //                invocation.Proceed();
        //                unitOfWork.CommitUnitOfWork();
        //            }
        //        }
        //        catch
        //        {
        //            unitOfWork.RollbackTran();
        //            throw;
        //        }
        //    }
        //    else
        //    {
        //        invocation.Proceed();
        //    }
        //}
    }
}
